package Border;


import static org.junit.Assert.*;

import java.math.BigDecimal;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;

import SquarePackage.Direction;
import SquarePackage.NormalSquare;
import SquarePackage.Square;
import SquarePackage.TemperatureScale;

/**
 * testClass for the Border Hierarchy.(Door tests and Wall tests are included in this junit testcase)
 * @author Florian
 * @version	1.0
 */
public class BorderTest {

	private Border wall;
	private Border door;
	private Square square;
	private Square square1;
	private Square square2;
	private Square square3;
	private Square square4;
	private Map <Direction,Border> borders;
	private Direction directionOfBorder;
	private boolean isOpenDoor;
	private boolean isSlipperyWall;

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		square = new NormalSquare(50,new BigDecimal(30), TemperatureScale.CELSIUS);
		square1 = new NormalSquare(-30,new BigDecimal(80), TemperatureScale.CELSIUS);
		wall = new Wall(square, Direction.EAST);
		door = new Door(square1,Direction.EAST);
		square2 = new NormalSquare();
		square3 = new NormalSquare();
		square4 = new NormalSquare();

		directionOfBorder = Direction.NORTH;
		isOpenDoor = false;
		isSlipperyWall = false;
	}

	@Test(expected = IllegalArgumentException.class)
	public void setSquareIllegalTest(){
		Border wall1 = new Wall(square1,Direction.EAST);
	}
	@Test(expected=IllegalArgumentException.class)
	public void setSquareToManyIllegalTest(){
	    new NormalSquare(123,BigDecimal.ZERO,TemperatureScale.CELSIUS,wall,Direction.EAST);
		Square square2 = new NormalSquare(123,new BigDecimal(45), TemperatureScale.CELSIUS);
		wall.setSquare(square2);
		Square square3 = new NormalSquare();
		wall.setSquare(square3);
	}

	@Test
	public void demolishTest(){
		wall.demolish(square);
		assertEquals(null,wall.getIdentifier());
		assertEquals(null,wall.getSecondSquare());
	}
	@Test
	public void constructor_twoSquares(){
		Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
		Wall wall = new Wall(square3, square4, directionOfBorder, isSlipperyWall);

		assertFalse(door.isOpen());
		assertFalse(wall.isSlippery());
		assertFalse(door.isTerminated());
		assertFalse(wall.isTerminated());
		assertEquals(square1.getBorderAt(directionOfBorder), door);
		assertEquals(square2.getBorderAt(directionOfBorder.getOpposite()), door);
		assertEquals(square3.getBorderAt(directionOfBorder), wall);
		assertEquals(square4.getBorderAt(directionOfBorder.getOpposite()), wall);
	}

	@Test
	public void constructor_oneSquare(){
		Door door = new Door(square1, directionOfBorder, isOpenDoor);
		Wall wall = new Wall(square3, directionOfBorder, isSlipperyWall);
		assertFalse(door.isOpen());
		assertFalse(wall.isSlippery());
		assertFalse(door.isTerminated());
		assertFalse(wall.isTerminated());
		assertEquals(square1.getBorderAt(directionOfBorder), door);
		assertEquals(square3.getBorderAt(directionOfBorder), wall);

	}
	@Test
	public void terminateBorderWithOneSquare(){
		Door door = new Door(square1, directionOfBorder, isOpenDoor);
		Wall wall = new Wall(square3, directionOfBorder, isSlipperyWall);               

		door.terminate();
		wall.terminate();

		assertTrue(door.isTerminated());
		assertTrue(wall.isTerminated());
		assertEquals(door.getIdentifier(), null);
		assertEquals(door.getSecondSquare(), null);
		assertEquals(wall.getIdentifier(), null);
		assertEquals(wall.getSecondSquare(), null);
		assertFalse(square1.hasBorder(directionOfBorder));
		assertFalse(square3.hasBorder(directionOfBorder));
	} 

	@Test
	public void terminateBorderWithTwoSquares(){
		Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
		Wall wall = new Wall(square3, square4, directionOfBorder, isSlipperyWall);

		door.terminate();
		wall.terminate();

		assertTrue(door.isTerminated());
		assertTrue(wall.isTerminated());
		assertEquals(door.getIdentifier(), null);
		assertEquals(door.getSecondSquare(), null);
		assertEquals(wall.getIdentifier(), null);
		assertEquals(wall.getSecondSquare(), null);
		assertFalse(square1.hasBorder(directionOfBorder));
		assertFalse(square2.hasBorder(directionOfBorder));
		assertFalse(square3.hasBorder(directionOfBorder));
		assertFalse(square4.hasBorder(directionOfBorder));
	}


	@Test (expected = IllegalArgumentException.class)
	public void getOtherSquareTest_NonEffectiveSquareForDoor(){
		Door door = new Door(square1, directionOfBorder, isOpenDoor);
		door.getOtherSquare(null);
	}

	@Test (expected = IllegalArgumentException.class)
	public void getOtherSquareTest_NonEffectiveSquareForWall(){
		Wall wall = new Wall(square1, directionOfBorder, isSlipperyWall);
		wall.getOtherSquare(null);
	}

	@Test (expected = IllegalArgumentException.class)
	public void getOtherSquareTest_NoneOfTheSquaresForDoor(){
		Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
		door.getOtherSquare(square3);
	}

	@Test (expected = IllegalArgumentException.class)
	public void getOtherSquareTest_NoneOfTheSquaresForWall(){
		Wall wall = new Wall(square1, square2, directionOfBorder, isSlipperyWall);
		wall.getOtherSquare(square3);
	}

	@Test
	public void getOtherSquareTest_LegalCaseForDoor(){
		Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
		assertEquals(square2, door.getOtherSquare(square1));
		assertEquals(square1, door.getOtherSquare(square2));
	}

	@Test
	public void getOtherSquareTest_LegalCaseForWall(){
		Wall wall = new Wall(square1, square2, directionOfBorder, isSlipperyWall);

		assertEquals(square2, wall.getOtherSquare(square1));
		assertEquals(square1, wall.getOtherSquare(square2));
	}
	
	@Test
	public void isValidDirectionTest_LegalCaseForDoor(){
		assertTrue(door.isValidDirection(directionOfBorder));
	}

	@Test
	public void isValidDirectionTest_LegalCaseForWall(){
		assertTrue(wall.isValidDirection(directionOfBorder));

	}
	@Test
	public void hasProperSquaresTest_LegalCaseForDoor(){
		Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
		assertTrue(door.hasProperSquares());
	}

	@Test
	public void hasProperSquaresTest_LegalCaseForWall(){
		Wall wall = new Wall(square1, square2, directionOfBorder, isSlipperyWall);
		assertTrue(wall.hasProperSquares());
	}
	@Test
	public void hasSquareTest_LegalCaseForDoor(){
		Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
		assertFalse(door.hasSquare(square3));
		assertFalse(door.hasSquare(square4));
		assertTrue(door.hasSquare(square1));
		assertTrue(door.hasSquare(square2));
	}

	@Test
	public void hasSquareTest_LegalCaseForWall(){
		Wall wall = new Wall(square1, square2, directionOfBorder, isSlipperyWall);
		assertFalse(wall.hasSquare(square3));
		assertFalse(wall.hasSquare(square4));
		assertTrue(wall.hasSquare(square1));
		assertTrue(wall.hasSquare(square2));
	}

	///////////////////////////////////////////////////////////////////////////////////////////////////////

	@Test
	public void demolishTest_LegalCaseForDoorFirstSquareEffectiveSecondSquare(){
		Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
		square1.terminate();
		assertEquals(door.getIdentifier(),square2);
	}

	@Test
	public void demolishTest_LegalCaseForDoorFirstSquareNoneffectiveSecondSquare(){
		Door door = new Door(square1, directionOfBorder, isOpenDoor);
		square1.terminate();
		assertTrue(door.isTerminated());
	}

	@Test
	public void demolishTest_LegalCaseForDoorSecondSquareEffectiveFirstSquare(){
		Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
		square2.terminate();
		assertEquals(door.getSecondSquare(), null);
	}

	@Test
	public void demolishTest_LegalCaseForDoorSecondSquareNoneffectiveFirstSquare(){
		Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
		square1.terminate();
		square2.terminate();
		assertTrue(door.isTerminated());

	}

	@Test
	public void demolishTest_LegalCaseForWallFirstSquareEffectiveSecondSquare(){
		Wall wall = new Wall(square1, square2, directionOfBorder, isSlipperyWall);
		square1.terminate();
		assertEquals(wall.getIdentifier(),square2);
	}

	@Test
	public void demolishTest_LegalCaseForWallFirstSquareNoneffectiveSecondSquare(){
		Wall wall = new Wall(square1, directionOfBorder, isSlipperyWall);
		square1.terminate();
		assertTrue(wall.isTerminated());
	}

	@Test
	public void demolishTest_LegalCaseForWallSecondSquareEffectiveFirstSquare(){
		Wall wall = new Wall(square1, square2, directionOfBorder, isSlipperyWall);
		square2.terminate();
		assertEquals(wall.getSecondSquare(), null);
	}

	@Test
	public void demolishTest_LegalCaseForWallSecondSquareNoneffectiveFirstSquare(){
		Wall wall = new Wall(square1, square2, directionOfBorder, isSlipperyWall);
		square1.terminate();
		square2.terminate();
		assertTrue(wall.isTerminated());
	}
//////////////////////////////////////////////////////////////////////////////////////
    @Test
    public void constructorTest(){
             Door door = new Door(square1, square2, directionOfBorder, isOpenDoor);
             
             assertFalse(door.isOpen());
             assertFalse(door.isTerminated());
             assertFalse(door.isOpen());
             assertEquals(square1.getBorderAt(directionOfBorder), door);
             assertEquals(square2.getBorderAt(directionOfBorder.getOpposite()), door);
             
    }
    
    @Test
    public void constructorTest2(){
            Door door = new Door(square1, directionOfBorder, isOpenDoor);
            
            assertFalse(door.isOpen());
            assertFalse(door.isTerminated());
            assertFalse(door.isOpen());
            assertEquals(square1.getBorderAt(directionOfBorder), door);
             
    }
    
//////////////////////////////////////////////////////////////////////////////////////
    
    @Test
    public void openDoorTest(){
            boolean isOpen = false;
            Door door = new Door(square1, square2, directionOfBorder, isOpen);
            assertFalse(door.isOpen());
            
    }
    
    @Test
    public void closeDoorTest(){
            boolean isOpen = true;
            Door door = new Door(square1, square2, directionOfBorder, isOpen);
            assertTrue(door.isOpen());
    }
    

    
    @Test
    public void isValidDirectionTest_LegalCase(){
            assertTrue(door.isValidDirection(directionOfBorder));
    }
    
    @Test
    public void isValidDirectionTest_NoneffectiveDirectionCase(){
            assertFalse(door.isValidDirection(null));
    }
    
    @Test
    public void isValidDirectionTest_IllegalDirectionCeilingCase(){
            assertFalse(door.isValidDirection(Direction.CEILING));
    }
    
    @Test
    public void isValidDirectionTest_IllegalDirectionFloorCase(){
            assertFalse(door.isValidDirection(Direction.FLOOR));

}}